/* Copyright (c) 2020-2025 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "csr_synergy.h"

#ifndef EXCLUDE_GATT_XPAN_CLIENT_MODULE

#include "gatt_xpan_client_msg_handler.h"
#include "gatt_xpan_client_debug.h"
#include "gatt_xpan_client_init.h"
#include "gatt_xpan_client_discovery.h"
#include "gatt_xpan_client_common.h"

#include "gatt_xpan_client_read.h"
#include "gatt_xpan_client_write.h"

#include "gatt_xpan_client_notification.h"
#include "csr_bt_gatt_lib.h"
#include "gatt_lib.h"

static void xpanClientHandleRegisterCfm(const CsrBtGattRegisterCfm *cfm)
{
    GXPANC * xpanClient = ServiceHandleGetInstanceData(cfm->context);
    bool result = FALSE;
    if(xpanClient)
    {
        if (cfm->resultCode == CSR_BT_GATT_RESULT_SUCCESS)
        {
            CsrBtTypedAddr address;
            xpanClient->srvcElem->gattId = cfm->gattId;
            if (GattClientUtilFindAddrByConnId(xpanClient->srvcElem->cid, &address))
            {
                result = TRUE;
                GattClientRegisterServiceReqSend(xpanClient->srvcElem->gattId,
                                                 xpanClient->clientData.startHandle,
                                                 xpanClient->clientData.endHandle,
                                                 address);
                if(xpanClient->clientDataIsSet == FALSE)
                {
                    GattDiscoverAllCharacOfAServiceReqSend(xpanClient->srvcElem->gattId,
                                                           xpanClient->srvcElem->cid,
                                                           xpanClient->clientData.startHandle,
                                                           xpanClient->clientData.endHandle);
                }
            }
        }
    }

    if(result == FALSE)
    {
        GATT_XPAN_CLIENT_ERROR("Register with the GATT Manager failed!\n");
        if(xpanClient)
        {
            gattXpanClientSendInitCfm(xpanClient, GATT_XPAN_CLIENT_STATUS_FAILED);
        }
    }
}

/****************************************************************************/
static void xpanClientHandleGattManagerMsg(void *task, MsgId id, Msg msg)
{
    GXPANC *xpanClient = (GXPANC *)task;

    switch (id)
    {
        case CSR_BT_GATT_REGISTER_CFM:
        {
            xpanClientHandleRegisterCfm((const CsrBtGattRegisterCfm *)msg);
        }
		break;
        case CSR_BT_GATT_DISCOVER_CHARAC_CFM:
        {
            xpanClientHandleDiscoverAllCharacteristicsResp(xpanClient,
                                                           (const GATT_MANAGER_DISCOVER_ALL_CHARACTERISTICS_CFM_T *)msg);
        }
        break;
        case CSR_BT_GATT_DISCOVER_CHARAC_DESCRIPTORS_CFM:
        {
            xpanClientHandleDiscoverAllCharacteristicDescriptorsResp(xpanClient,
                                                                     (const GATT_MANAGER_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM_T *)msg);
        }
        break;
        case CSR_BT_GATT_WRITE_CFM:
        {
            /* Set Notification Confirmation */
            xpanClientHandleWriteValueRespCfm(xpanClient,
                                              (const CsrBtGattWriteCfm*)msg);
        }
        break;
        case CSR_BT_GATT_READ_CFM:
        {
            xpanClientHandleReadValueResp(xpanClient,
                                          (const CsrBtGattReadCfm *)msg);
        }
        break;

        case CSR_BT_GATT_CLIENT_NOTIFICATION_IND:
        {
            xpanClientHandleClientNotification(xpanClient,
                                              (const CsrBtGattClientNotificationInd *)msg);
        }
        break;

        default:
        {
            /* Unrecognised GATT Manager message */
            GATT_XPAN_CLIENT_WARNING("GXPANC: XPAN Client GattMgr Msg not handled [0x%x]\n", id);
        }
        break;
    }
}

/****************************************************************************/
/*
static void xpanClientSetFlagWritePending(GXPANC * xpan_client,
                                          xpan_client_control_point_opcodes_t opcode)
{
    switch(opcode)
    {
        case xpan_client_some_xpan_operation_op:
            xpan_client->pending_cmd = xpan_client_some_xpan_operation_pending;
        break;

        default:
        break;
    }
}
*/
/***************************************************************************/
static void xpanClientHandleInternalMessage(void * task, MsgId id, Msg msg)
{
    GXPANC * xpanClient = (GXPANC *)task;

    GATT_XPAN_CLIENT_INFO("Message id (%d)\n",id);

    if (xpanClient)
    {
        switch(id)
        {
            case XPAN_CLIENT_INTERNAL_MSG_INIT_READ:
            {
                uint16 handle = ((const XPAN_CLIENT_INTERNAL_MSG_INIT_READ_T*)msg)->handle;

                CsrBtGattReadReqSend(xpanClient->srvcElem->gattId,
                         xpanClient->srvcElem->cid,
                         handle,
                         0);
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_READ_CCC:
            {
                uint16 handle = ((const XPAN_CLIENT_INTERNAL_MSG_READ_CCC_T*)msg)->handle;

                CsrBtGattReadReqSend(xpanClient->srvcElem->gattId,
                         xpanClient->srvcElem->cid,
                         handle,
                         0);
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_READ:
            {
                uint16 handle = ((const XPAN_CLIENT_INTERNAL_MSG_READ_T *)msg)->handle;

                CsrBtGattReadReqSend(xpanClient->srvcElem->gattId,
                         xpanClient->srvcElem->cid,
                         handle,
                         0);
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_NOTIFY_READ:
            {
                uint16 handle = ((const XPAN_CLIENT_INTERNAL_MSG_NOTIFY_READ_T *)msg)->handle;

                CsrBtGattReadReqSend(xpanClient->srvcElem->gattId,
                        xpanClient->srvcElem->cid,
                         handle,
                         0);
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_NOTIFICATION_REQ:
            {
                XpanClientInternalMsgSetNotification* message = (XpanClientInternalMsgSetNotification*) msg;

               xpanClientHandleInternalRegisterForNotification(xpanClient,
                                                                message->notificationsEnable,
                                                                message->handle);
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_CONNECT_SSID_OPCODE_REQ:
            {
                xpanWriteControlPointConnectSsidReq(xpanClient,
                                                  (&((const XpanClientInternalMsgConnectSsidReq *)msg)->connectSsidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_CONNECT_SSID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_DISCONNECT_SSID_OPCODE_REQ:
            {
                xpanWriteControlPointDisconnectSsidReq(xpanClient,
                                                  (&((const XpanClientInternalMsgDisconnectSsidReq *)msg)->disconnectSsidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_DISCONNECT_SSID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_CONNECTED_SSID_OPCODE_REQ:
            {
                xpanWriteControlPointConnectedSsidReq(xpanClient,
                                                  (&((const XpanClientInternalMsgConnectedSsidReq *)msg)->connectedSsidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_CONNECTED_SSID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_AVAILABLE_SSID_OPCODE_REQ:
            {
                xpanWriteControlPointAvailableSsidReq(xpanClient,
                                                     (&((const XpanClientInternalMsgAvailableSsidReq *)msg)->availableSsidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_AVAILABLE_SSID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_RELATED_SSIDS_OPCODE_REQ:
            {
                xpanWriteControlPointRelatedSsidsReq(xpanClient,
                                                     (&((const XpanClientInternalMsgRelatedSsidsReq *)msg)->relatedSsidsOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_RELATED_SSIDS_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_MDNS_SRV_UUID_OPCODE_REQ:
            {
                xpanWriteControlPointMdnsSrvUuidReq(xpanClient,
                                                     (&((const XpanClientInternalMsgMdnsSrvUuidReq *)msg)->mdnsSrvUuidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_MDNS_SRV_UUID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_REMOVE_SSID_OPCODE_REQ:
            {
                xpanWriteControlPointRemoveSsidReq(xpanClient,
                                                     (&((const XpanClientInternalMsgRemoveSsidReq *)msg)->removeSsidOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_REMOVE_SSID_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_L2CAP_TCP_PORT_OPCODE_REQ:
            {
                xpanWriteControlPointL2capTcpPortReq(xpanClient,
                                                     (&((const XpanClientInternalMsgL2capTcpPortReq *)msg)->l2capTcpPortOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_L2CAP_TCP_PORT_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_UDP_PORT_OPCODE_REQ:
            {
                xpanWriteControlPointUdpPortReq(xpanClient,
                                                     (&((const XpanClientInternalMsgUdpPortReq *)msg)->udpPortOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_UDP_PORT_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_ETHER_TYPE_OPCODE_REQ:
            {
                xpanWriteControlPointEtherTypeReq(xpanClient,
                                                     (&((const XpanClientInternalMsgEtherTypeReq *)msg)->etherTypeOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_ETHER_TYPE_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_MAC_ADDRESS_OPCODE_REQ:
            {
                xpanWriteControlPointMacAddressReq(xpanClient,
                                                     (&((const XpanClientInternalMsgMacAddressReq *)msg)->macAddressOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_MAC_ADDRESS_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_BEARER_PREFERENCE_RESPONSE_OPCODE_REQ:
            {
                xpanWriteControlPointBearerPreferenceResponseReq(xpanClient,
                                                     (&((const XpanClientInternalMsgBearerPreferenceResponseReq *)msg)->bearerPreferenceResponseOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_BEARER_PREFERENCE_RESPONSE_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_UPDATE_BEACON_PARAMETERS_OPCODE_REQ:
            {
                xpanWriteControlPointUpdateBeaconParametersReq(xpanClient,
                                                     (&((const XpanClientInternalMsgUpdateBeaconParametersReq *)msg)->updateBeaconParametersOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_UPDATE_BEACON_PARAMETERS_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_SAP_POWER_STATE_RESPONSE_OPCODE_REQ:
            {
                xpanWriteControlPointSapPowerStateResponseReq(xpanClient,
                                                     (&((const XpanClientInternalMsgSapPowerStateResponseReq *)msg)->sapPowerStateResponseOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_SAP_POWER_STATE_RESPONSE_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_CLIENT_FEATURES_OPCODE_REQ:
            {
                xpanWriteControlPointClientFeaturesReq(xpanClient,
                                                      (&((const XpanClientInternalMsgClientFeaturesReq *)msg)->clientFeaturesOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_CLIENT_FEATURES_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_AUDIO_BEARER_SWITCH_REQUEST_OPCODE_REQ:
            {
                 xpanWriteControlPointAudioBearerSwitchRequestReq(xpanClient,
                                                                 (&((const XpanClientInternalMsgAudioBearerSwitchRequestReq *)msg)->audioBearerSwitchRequestOp));

                 xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_AUDIO_BEARER_SWITCH_REQUEST_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_TWT_CONFIGURATION_REQ:
            {
                xpanWriteTwtConfigurationRequestReq(xpanClient,
                                                   (&((const XpanClientInternalMsgTwtConfigurationReq *)msg)->twtConfiguration));

                /* The xpanClient->pending_cmd is only used for Control Point Opcode responses
                 * xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_TWT_CONFIGURATION_CFM;
                 */
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_TERMINATE_TWT_SESSION_REQ:
            {
                xpanWriteTwtConfigurationRequestReq(xpanClient, NULL /* A TWT Session is terminated by sending an empty payload */);

                /* The xpanClient->pending_cmd is only used for Control Point Opcode responses
                 * xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_TWT_CONFIGURATION_CFM;
                 */
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_WIFI_SCAN_RESULTS_OPCODE_REQ:
            {
                xpanWriteControlPointWiFiScanResultsReq(xpanClient,
                                                       (XpanClientInternalMsgWiFiScanResultsReq *)msg);

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_WIFI_SCAN_RESULTS_OPCODE_CFM;
            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_CHANNEL_SWITCH_ANNOUNCEMENT_OPCODE_REQ:
            {
                xpanWriteControlPointChannelSwitchAnnouncementReq(xpanClient,
                                                                 (&((const XpanClientInternalMsgChannelSwitchAnnouncementReq *)msg)->channelSwitchAnnouncementOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_CHANNEL_SWITCH_ANNOUNCEMENT_OPCODE_CFM;

            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_UDP_SYNC_PORT_OPCODE_REQ:
            {
                xpanWriteControlPointUdpSyncPortReq(xpanClient,
                                                   (&((const XpanClientInternalMsgUdpSyncPortReq *)msg)->udpSyncPortOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_UDP_SYNC_PORT_OPCODE_CFM;

            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_ROAMING_REQUEST_OPCODE_REQ:
            {
                xpanWriteControlPointRoamingRequestReq(xpanClient);

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_ROAMING_REQUEST_OPCODE_CFM;

            }
            break;

            case XPAN_CLIENT_INTERNAL_MSG_WRITE_MULTICAST_MAC_ADDRESS_OPCODE_REQ:
            {
                xpanWriteControlPointMulticastMacAddressReq(xpanClient,
                                                           (&((const XpanClientInternalMsgMulticastMacAddressReq *)msg)->multicastMacAddresOp));

                xpanClient->pending_cmd = GATT_XPAN_CLIENT_WRITE_MULTICAST_MAC_ADDRESS_OPCODE_CFM;

            }
            break;


            default:
            {
                /* Internal unrecognised messages */
                GATT_XPAN_CLIENT_WARNING("Unknown Message received from Internal To lib \n");
            }
            break;
        }
    }
}

/****************************************************************************/
void XpanClientMsgHandler(void **gash)
{
    CsrUint16 eventClass = 0;
    void *message = NULL;
    gatt_xpan_client *inst = *((gatt_xpan_client **)gash);

    if (CsrSchedMessageGet(&eventClass, &message))
    {
        switch (eventClass)
        {
            case CSR_BT_GATT_PRIM:
            {
                CsrBtGattPrim *id = message;
                /* Retrieve correct client using gattid in the message */
                GXPANC * xpan_client = (GXPANC *) GetServiceClientByGattMsg(&inst->serviceHandleList, message);
                void *msg = GetGattManagerMsgFromGattMsg(message, id);

                if (xpan_client)
                    xpanClientHandleGattManagerMsg(xpan_client, *id, msg);

                GattFreeUpstreamMessageContents(msg);

                if(msg && msg!=message)
                    CsrPmemFree(msg);
            }
                break;
            case XPAN_CLIENT_PRIM:
            {
                XpanClientInternalMsgType *id = (XpanClientInternalMsgType *)message;
                GXPANC *xpan_client = (GXPANC *) GetServiceClientByServiceHandle(message);
                xpanClientHandleInternalMessage(xpan_client, *id, message);
            }
                break;
            default:
			{
                GATT_XPAN_CLIENT_WARNING("GXPANC: Client Msg not handled [0x%x]\n", eventClass);
			}
				break;
        }
        SynergyMessageFree(eventClass, message);
    }
}

#endif /* EXCLUDE_GATT_XPAN_CLIENT_MODULE */